package com.huiminpay.transaction.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.huiminpay.common.cache.domain.BusinessException;
import com.huiminpay.common.cache.domain.CommonErrorCode;
import com.huiminpay.common.cache.util.AmountUtil;
import com.huiminpay.common.cache.util.EncryptUtil;
import com.huiminpay.common.cache.util.PaymentUtil;
import com.huiminpay.merchant.api.AppService;
import com.huiminpay.merchant.api.MerchantService;
import com.huiminpay.paymentagent.api.PayChannelAgentService;
import com.huiminpay.paymentagent.api.conf.AliConfigParam;
import com.huiminpay.paymentagent.api.dto.AlipayBean;
import com.huiminpay.paymentagent.api.dto.PaymentResponseDTO;
import com.huiminpay.transaction.api.PayChannelService;
import com.huiminpay.transaction.api.TransactionService;
import com.huiminpay.transaction.convert.PayOrderConvert;
import com.huiminpay.transaction.dto.PayChannelParamDTO;
import com.huiminpay.transaction.dto.PayOrderDTO;
import com.huiminpay.transaction.dto.QRCodeDTO;
import com.huiminpay.transaction.entity.PayOrder;
import com.huiminpay.transaction.mapper.PayOrderMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Value;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

/**
 * ClassName:TransactionServiceImpl
 * Package:com.huiminpay.transaction.service
 * Time: 2024/7/27
 */
@Slf4j
@Service
public class TransactionServiceImpl implements TransactionService {
    /**
     * 支付入口url
     */
    @Value("${huiminpay.payurl}")
    private String payUrl;

    @Reference
    MerchantService merchantService;

    @Reference
    AppService appService;

    @Reference
    PayChannelAgentService payChannelAgentService;

    @Resource
    PayChannelService payChannelService;

    @Resource
    PayOrderMapper payOrderMapper;

    /**
     * 生成门店二维码
     *
     * @param qrCodeDTO 传入merchantId,appId、storeid、channel、subject、body
     * @return 支付入口URL，将二维码的参数组成json并用base64编码
     * @throws BusinessException
     */
    @Override
    public String createStoreQRCode(QRCodeDTO qrCodeDTO) throws BusinessException {
        //1、校验应用和门店
        verifyAppAndStore(qrCodeDTO.getMerchantId(), qrCodeDTO.getAppId(), qrCodeDTO.getStoreId());
        //2、生成支付信息
        PayOrderDTO payOrderDTO = new PayOrderDTO();
        payOrderDTO.setMerchantId(qrCodeDTO.getMerchantId());
        payOrderDTO.setAppId(qrCodeDTO.getAppId());
        payOrderDTO.setStoreId(qrCodeDTO.getStoreId());
        payOrderDTO.setSubject(qrCodeDTO.getSubject());//显示订单标题
        payOrderDTO.setChannel("huimin_c2b");//服务类型
        payOrderDTO.setBody(qrCodeDTO.getBody());//订单内容
        String jsonString = JSON.toJSONString(payOrderDTO);
        log.info("transaction service createStoreQRCode,JsonString is {}", jsonString);
        //3、将支付信息保存在票据中
        String ticket = EncryptUtil.encodeUTF8StringBase64(jsonString);
        //4、生成支付入口URL
        String payEntryUrl = payUrl + ticket;
        log.info("transaction service createStoreQRCode,pay‐entry is {}", payEntryUrl);
        return payEntryUrl;
    }

    /**
     * 保存支付宝订单在交易服务
     *
     * @param payOrderDTO 订单信息
     * @return
     * @throws BusinessException
     */
    @Override
    public PaymentResponseDTO submitOrderByAli(PayOrderDTO payOrderDTO) throws BusinessException {
        //保存订单
        payOrderDTO.setPayChannel("ALIPAY_WAP");
        //保存订单到聚合支付平台数据库
        PayOrderDTO save = save(payOrderDTO);
        //调用支付代理服务请求第三方支付系统
        PaymentResponseDTO paymentResponseDTO = alipayH5(save.getTradeNo());
        return paymentResponseDTO;
    }

    /**
     * 更新订单支付状态
     *
     * @param tradeNo           闪聚平台订单号
     * @param payChannelTradeNo 支付宝或微信的交易流水号(第三方支付系统的订单)
     * @param state             订单状态  交易状态支付状态,0-订单生成,1-支付中(目前未使用),2-支付成功,4-关闭 5--失败
     */
    @Override
    public void updateOrderTradeNoAndTradeState(String tradeNo, String payChannelTradeNo, String state) throws BusinessException {
        LambdaUpdateWrapper<PayOrder> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(PayOrder::getTradeNo, tradeNo)
                .set(PayOrder::getPayChannelTradeNo, payChannelTradeNo)
                .set(PayOrder::getTradeState, state);

        if (state!=null&& "2".equals(state)) {
            updateWrapper.set(PayOrder::getPaySuccessTime, LocalDateTime.now());
        }
        payOrderMapper.update(null, updateWrapper);
    }

    /**
     * 校验应用和门店是否属于当前商户
     *
     * @param merchantId 商户id
     * @param appId      商户应用id
     * @param storeId    门店id
     */
    private void verifyAppAndStore(Long merchantId, String appId, Long storeId) {
        Boolean aBoolean1 = appService.queryAppInMerchant(appId, merchantId);
        if (!aBoolean1) {
            throw new BusinessException(CommonErrorCode.E_200005); //应用不属于该商户
        }
        Boolean aBoolean = merchantService.queryStoreInMerchant(storeId, merchantId);
        if (!aBoolean) {
            throw new BusinessException(CommonErrorCode.E_200006); //门店不属于该商户
        }


    }

    /**
     * 保存订单到惠民平台数据库
     *
     * @param payOrderDTO 订单信息
     * @return 订单信息
     * @throws BusinessException
     */
    private PayOrderDTO save(PayOrderDTO payOrderDTO) throws BusinessException {
        PayOrder payOrder = PayOrderConvert.INSTANCE.dto2entity(payOrderDTO);
        //订单号
        payOrder.setTradeNo(PaymentUtil.genUniquePayOrderNo()); //采用雪花算法生成唯一订单号
        //订单创建时间
        payOrder.setCreateTime(LocalDateTime.now());
        //设置订单过期时间，为30分钟
        payOrder.setExpireTime(LocalDateTime.now().plus(30, ChronoUnit.MINUTES));
        //设置支付币种 默认人民币
        payOrder.setCurrency("CNY");
        payOrder.setTradeState("0"); //订单状态 0：订单生成
        //保存订单
        payOrderMapper.insert(payOrder);
        //返回订单信息
        return PayOrderConvert.INSTANCE.entity2dto(payOrder);
    }

    /**
     * 根据订单号查询订单信息
     *
     * @param tradeNo 订单号
     * @return 订单信息
     */
    private PayOrderDTO queryPayOrder(String tradeNo) {
        // 创建LambdaQueryWrapper对象用于构建查询条件
        LambdaQueryWrapper<PayOrder> queryWrapper = new LambdaQueryWrapper<>();
        // 设置查询条件：订单号等于传入的tradeNo
        queryWrapper.eq(PayOrder::getTradeNo, tradeNo);
        // 使用payOrderMapper执行查询，获取满足条件的PayOrder对象
        PayOrder payOrder = payOrderMapper.selectOne(queryWrapper);
        // 将查询到的PayOrder对象转换为PayOrderDTO对象并返回
        return PayOrderConvert.INSTANCE.entity2dto(payOrder);
    }


    /**
     * 调用支付宝下单接口
     *
     * @param tradeNo 订单号
     * @return 支付宝返回的支付信息
     */
    private PaymentResponseDTO alipayH5(String tradeNo) {
        // 构建支付实体
        AlipayBean alipayBean = new AlipayBean();

        //根据订单号查询订单详情
        PayOrderDTO payOrderDTO = queryPayOrder(tradeNo);
        alipayBean.setOutTradeNo(payOrderDTO.getTradeNo());
        alipayBean.setSubject(payOrderDTO.getSubject());
        String totalAmount = null;
        // 金额单位为元
        try {
            totalAmount = AmountUtil.changeF2Y(payOrderDTO.getTotalAmount().toString());
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(CommonErrorCode.E_300006); //金额格式错误
        }
        alipayBean.setTotalAmount(totalAmount);
        alipayBean.setBody(payOrderDTO.getBody());
        alipayBean.setStoreId(payOrderDTO.getStoreId());
        alipayBean.setExpireTime("30m");

        //根据应用、服务类型和支付渠道查询支付渠道相应参数
        PayChannelParamDTO payChannelParamDTO = payChannelService.queryPayChannelParamByAppIdAndPlatformChannelCodeAndPayChannelCode(payOrderDTO.getAppId(),
                payOrderDTO.getChannel(), "ALIPAY_WAP");
        if (payChannelParamDTO == null) {
            throw new BusinessException(CommonErrorCode.E_300007); //原始支付渠道为空
        }

        //PayChannelParamDTO中的支付渠道参数传给AliConfigParam
        AliConfigParam aliConfigParam = JSON.parseObject(payChannelParamDTO.getParam(), AliConfigParam.class);

        //设置字符编码
        aliConfigParam.setCharset("UTF-8");

        //设置网关
        //aliConfigParam.setUrl("https://openapi-sandbox.dl.alipaydev.com/gateway.do");

        // 调用支付渠道代理服务，调用支付宝手机WAP下单接口
        PaymentResponseDTO payOrderResponse = payChannelAgentService.createPayOrderByAliWAP(aliConfigParam, alipayBean);
        log.info("支付宝H5支付响应Content:" + payOrderResponse);

        return payOrderResponse;
    }


}
